﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using StockTrader.DAL.HastcAdapter.FileMonitor.BusinessLogic;
using System.IO;
using System.Threading;
using StockTrader.DAL.HastcAdapter.FileParser.Structure;
using System.Xml;
using StockTrader.DAL.HastcAdapter.FileMonitor.DataAccess;
using StockTrader.DAL.HastcAdapter.Config;
using ZipLibrary.Zip;
using StockTrader.DAL.HoseAdapter.Lib;


namespace StockTrader.DAL.HastcAdapter.FileMonitor
{
    public partial class frmMain : Form
    {
        private AsyncDataProcessor processor;
        private System.Timers.Timer pollTimer = new System.Timers.Timer();
        private bool _isTodayBackupSuccess = false;
        private bool _isRecoverSuccess = false;


        public frmMain()
        {
            InitializeComponent();
        }

        private void frmMain_Load(object sender, EventArgs e)
        {
            try
            {
                UpdateUI();
            }
            catch (System.Exception ex)
            {
                MessageBox.Show(ex.Message);
                return;
            }
            //ms = TransSchedule.getMarketState();
        }

        private void btnExit_Click(object sender, EventArgs e)
        {
            Environment.Exit(1);
        }

        private void btnStart_Click(object sender, EventArgs e)
        {
            CleaningFiles(Directory.GetCurrentDirectory(), "XML");

            btnStart.Enabled = false;
            btnBackup.Enabled = true;
            btnRecovery.Enabled = true;
            STS_MARKETINFO mkt = TransSchedule.getMarketInfo();

            BeginOfDay();

            pollTimer.Interval = Settings.READ_INTERVAL;
            pollTimer.Enabled = true;
            pollTimer.Elapsed += new System.Timers.ElapsedEventHandler(pollTimer_Elapse);
        }

        public static void Unzip(string filesname)
        {
            ZipInputStream s = null;
            FileStream streamWriter = null;
            try
            {
                using (s = new ZipInputStream(File.OpenRead(filesname)))
                {
                    ZipEntry theEntry;
                    theEntry = s.GetNextEntry();
                    while (theEntry != null)
                    {
                        using (streamWriter = File.Create(".\\" + @"\" + theEntry.Name))
                        {
                            int size = 2048;
                            byte[] data = new byte[2048];
                            while (true)
                            {
                                size = s.Read(data, 0, data.Length);
                                if (size > 0)
                                {
                                    streamWriter.Write(data, 0, size);
                                }
                                else
                                {
                                    streamWriter.Close();
                                    break;
                                }
                            }
                        }
                        theEntry = s.GetNextEntry();
                    }
                }
            }
            catch (Exception ex)
            {
                throw ex;
                return;
            }
        }

        void pollTimer_Elapse(object sender, System.Timers.ElapsedEventArgs e)//()
        {
            try
            {
                STS_MARKETINFO mkt = TransSchedule.getMarketInfo();

                if (TransSchedule.IsTradingDate(mkt))
                {
                    UpdateUI();
                    MarketState ms = TransSchedule.getMarketState(mkt);
                    switch (ms)
                    {
                        case MarketState.BeginOfDay:
                            BeginOfDay();
                            break;
                        case MarketState.Working:
                            OrderAsyncUpdater();
                            break;
                        case MarketState.EndOfDay:
                            if ((DateTime.Now.Hour < 12) && (DateTime.Now.Hour > 10))
                                Backup();
                            EndOfDay();
                            break;
                        default:
                            break;
                    }
                }
                else
                    UpdateUI();
            }
            catch (Exception ex)
            {
                return;
            }
        }

        private void UpdateUI()
        {
            try
            {
                STS_MARKETINFO mkt = TransSchedule.getMarketInfo();
                DALclient dac = new DALclient();

                MethodInvoker updateButtonState = delegate
                {
                    btnRecovery.Enabled = !_isRecoverSuccess;
                    btnBackup.Enabled = !_isTodayBackupSuccess;
                };
                if (btnBackup.InvokeRequired || btnRecovery.InvokeRequired)
                {
                    btnBackup.Invoke(updateButtonState);
                    btnRecovery.Invoke(updateButtonState);
                }
                else
                    updateButtonState();


                MethodInvoker updateUIState = delegate
                {
                    lblMarketDate.Text = mkt.TRADING_DATE.ToString("dd/MM/yyyy ") + mkt.TIME;
                };
                if (lblMarketDate.InvokeRequired)
                {
                    lblMarketDate.Invoke(updateUIState);
                }
                else
                    updateUIState();

                MethodInvoker UIcounter = delegate
                {
                    lblStockNum.Text = dac.CountSTS_LE().ToString();
                    lblMarketNum.Text = dac.CountSTS_MARKETINFO().ToString();
                    lblStockNum.BackColor = Color.Green;
                    lblMarketNum.BackColor = Color.Green;
                };
                if (lblStockNum.InvokeRequired || lblMarketNum.InvokeRequired)
                {
                    lblStockNum.BackColor = Color.Red;
                    lblMarketNum.BackColor = Color.Red;
                    lblStockNum.Invoke(UIcounter);
                    lblMarketNum.Invoke(UIcounter);
                }
                else
                    UIcounter();

                MethodInvoker updateMarketUIState = delegate
                {
                    MarketState ms = TransSchedule.getMarketState(mkt);
                    switch (ms)
                    {
                        case MarketState.BeginOfDay:
                            lblMarketState.Text = "BeginOfDay";
                            break;
                        case MarketState.Working:
                            lblMarketState.Text = "Working";
                            break;
                        default:
                            lblMarketState.Text = "Closed";
                            break;
                    }
                };
                if (lblMarketState.InvokeRequired)
                {
                    lblMarketState.Invoke(updateMarketUIState);
                }
                else
                    updateMarketUIState();
            }
            catch
            {
                throw;
            }

        }

        private void GetDataFiles()
        {
            try
            {
                string srcFile1 = Settings.ROOT_STS + "STS_Info_Public.zip";
                string desFile1 = "STS_Info_Public.zip";
                string srcFile2 = Settings.ROOT_STS + "STS_Info_Private.zip";
                string desFile2 = "STS_Info_Private.zip";

                if (File.Exists(srcFile1) && File.Exists(srcFile2))
                {
                    try
                    {
                        CommonLib.SafeCopy(srcFile1, desFile1);
                        CommonLib.SafeCopy(srcFile2, desFile2);
                    }
                    catch
                    {
                        return;
                    }
                }
                Unzip(desFile1);
                Unzip(desFile2);
            }
            catch (System.Exception e)
            {
                throw e;
            }
        }

        private void AsyncUpdater()
        {
            try
            {
                string strXML = AppDomain.CurrentDomain.BaseDirectory.Replace("bin\\Debug\\", "") + "Config\\FileDir.xml";
                XmlTextReader rdr = new XmlTextReader(strXML);
                while (rdr.Read())
                {
                    if (rdr.Name.CompareTo("FileConfig") == 0)
                    {
                        switch (getClassNameByClientID(rdr.ReadSubtree()))
                        {
                            case "STS_STOCKSINFO":
                                processor = new AsyncDataProcessor(lblStock, typeof(STS_STOCKSINFO));
                                processor.Execute();
                                break;
                            case "STS_ORDERS":
                                processor = new AsyncDataProcessor(lblOrder, typeof(STS_ORDERS));
                                processor.Execute();
                                break;
                            case "STS_TRADING_RESULT":
                                processor = new AsyncDataProcessor(lblTradingResult, typeof(STS_TRADING_RESULT));
                                processor.Execute();
                                break;
                            default:
                                break;
                        }
                    }
                }
                rdr.Close();
            }
            catch (System.Exception e)
            {
                return;
            }
        }

        private void OrderAsyncUpdater()
        {
            try
            {
                string strXML = AppDomain.CurrentDomain.BaseDirectory.Replace("bin\\Debug\\", "") + "Config\\FileDir.xml";
                XmlTextReader rdr = new XmlTextReader(strXML);
                while (rdr.Read())
                {
                    if (rdr.Name.CompareTo("FileConfig") == 0)
                    {
                        switch (getClassNameByClientID(rdr.ReadSubtree()))
                        {
                            case "STS_ORDERS":
                                processor = new AsyncDataProcessor(lblOrder, typeof(STS_ORDERS));
                                processor.Execute();
                                break;
                            case "STS_TRADING_RESULT":
                                processor = new AsyncDataProcessor(lblTradingResult, typeof(STS_TRADING_RESULT));
                                processor.Execute();
                                break;
                            default:
                                break;
                        }
                    }
                }
                rdr.Close();
            }
            catch (System.Exception e)
            {
                return;
            }
        }

        private void StockAsyncUpdater()
        {
            try
            {
                string strXML = AppDomain.CurrentDomain.BaseDirectory.Replace("bin\\Debug\\", "") + "Config\\FileDir.xml";
                XmlTextReader rdr = new XmlTextReader(strXML);
                while (rdr.Read())
                {
                    if (rdr.Name.CompareTo("FileConfig") == 0)
                    {
                        switch (getClassNameByClientID(rdr.ReadSubtree()))
                        {
                            case "STS_STOCKSINFO":
                                 processor = new AsyncDataProcessor(lblStock, typeof(STS_STOCKSINFO));
                                 processor.Execute();
                                break;
                            default:
                                break;
                        }
                    }
                }
                rdr.Close();
            }
            catch (System.Exception e)
            {
                return;
            }
        }

        private void Backup()
        {
            try
            {
                if (!_isTodayBackupSuccess)
                {
                    DALclient dac = new DALclient();
                    dac.BackupHastc();
                    _isTodayBackupSuccess = true;
                }
            }
            catch (Exception ex)
            {
                _isTodayBackupSuccess = false;
                btnBackup.Enabled = true;
                MessageBox.Show("Backup fail. " + ex.Message, "Error",
                                MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void BeginOfDay()
        {
            try
            {
                _isRecoverSuccess = false;
                _isTodayBackupSuccess = false;

                pollTimer.Interval = Settings.READ_INTERVAL;
                DALclient dac = new DALclient();
                dac.ClearHastc();
                OrderAsyncUpdater();
                StockAsyncUpdater();
            }
            catch
            {
                return;
            }
        }

        private void EndOfDay()
        {
            pollTimer.Interval = Settings.READ_INTERVAL_HIBERNATE;
        }

        private string getClassNameByClientID(XmlReader rdr)
        {
            string className = "";
            while (rdr.Read())
                if (rdr.Name == "ClassName")
                    className = rdr.ReadElementContentAsString();
            return className;
        }

        private void CleaningFiles(string folder, string extention)
        {
            try
            {
                string[] fileList = Directory.GetFiles(folder, "*." + extention);
                foreach (string udtFile in fileList)
                    File.Delete(udtFile);
            }
            catch
            {
                return;
            }
        }

        private void btnRecovery_Click(object sender, EventArgs e)
        {
            try
            {
                if ((MessageBox.Show("Data will be CLEAR and REINSERT. Are you sure?", "Confirmation", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) && (!_isRecoverSuccess))
                    BeginOfDay();
                else
                    _isRecoverSuccess = false;
            }
            catch (System.Exception ex)
            {
                _isRecoverSuccess = false;
            }
        }

        private void btnBackup_Click(object sender, EventArgs e)
        {
            Backup();
        }

        private void notifyIcon1_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            Show();
            WindowState = FormWindowState.Normal;
        }

        private void frmMain_Resize(object sender, EventArgs e)
        {
            if (FormWindowState.Minimized == WindowState)
                Hide();
        }

        private void frmMain_FormClosed(object sender, FormClosedEventArgs e)
        {
            notifyIcon1.Dispose();
        }

    }
}
